#ifndef _XTHREAD_INNER_H
#define _XTHREAD_INNER_H

#include "../xthread.h"
#include "list.h"
#include "xthread-timer.h"

#include <ucontext.h>

#ifdef __cplusplus
extern "C" {
#endif

// #define DEBUG_PRINT
// #define DEBUG_SCHED

#ifdef DEBUG_PRINT
#define XPRINT(fmt, ...) printf(fmt, ##__VA_ARGS__);
#else
#define XPRINT(fmt, ...)
#endif

#ifdef DEBUG_SCHED
#define XLOG(fmt, ...) printf(fmt, ##__VA_ARGS__);
#else
#define XLOG(fmt, ...)
#endif

#define XTHREAD_ALARM_MS  200    /*  n(100-999) msec to wakeup alarm.  */
#define XTHREAD_TIMESLICE_DFL  3

typedef enum {
    XTHREAD_READY = 0,
    XTHREAD_RUNNING,
    XTHREAD_BLOCK,
    XTHREAD_ZOMBIE,
} xthread_state_t;

typedef enum {
    XTHREAD_FLAG_DETACHED        = (1 << 0),     /* 线程分离标志，表示自己释放资源 */
    XTHREAD_FLAG_JOINEDBY               = (1 << 1),     /* 线程被其它线程等待中 */
    XTHREAD_FLAG_JOINING             = (1 << 2),     /* 线程正在等待其它线程 */
    XTHREAD_FLAG_CANCEL_DISABLE      = (1 << 3),     /* 线程不能被取消 */
    XTHREAD_FLAG_CANCEL_ASYCHRONOUS  = (1 << 4),     /* 线程收到取消信号时立即退出 */
    XTHREAD_FLAG_CANCELED            = (1 << 5),     /* 线程已经标记上取消点 */
} xthread_flags_t;

typedef struct  {
    list_t list;
    list_t global_list;
    xthread_t tid;          /* thread id */
    xthread_t parent_tid;          /* parent thread id */
    xthread_attr_t attr;
    xthread_state_t state;
    xthread_timer_t sleep_timer;    /* timer for  xthread_sleep */
    xthread_spin_lock_t lock;
    ucontext_t context;
    void * (*start_routine) (void *);
    void *arg;
    void *exit_status;
    int timeslice;
    int ticks;
    int flags;
} xthread_struct_t;

extern volatile clock_t __xthread_alarm_ticks;
extern volatile int __xthread_init_done;
extern xthread_struct_t *xthread_current;

void xthread_block(xthread_state_t state);
int xthread_unblock(xthread_struct_t *thread);

#define XTHREAD_CHECK_CANCELATION_POTINT(thread) \
    do { \
        if (!((thread)->flags & XTHREAD_FLAG_CANCEL_DISABLE) && \
            (thread)->flags & XTHREAD_FLAG_CANCELED) { \
            xthread_exit((void *) XTHREAD_FLAG_CANCELED); \
        } \
    } while (0)


#ifdef __cplusplus
}
#endif

#endif /* _XTHREAD_INNER_H */